/***************************************************************************************
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
*
* NEMU is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

#include "common.h"
#include "local-include/reg.h"
#include "macro.h"
#include <cpu/cpu.h>
#include <cpu/ifetch.h>
#include <cpu/decode.h>
#include <stdint.h>
#include "utils.h"

#define R(i) gpr(i)
#define Mr vaddr_read
#define Mw vaddr_write

extern void step_one(unsigned int *inst, int *ebreak, unsigned int *dnpc, unsigned int *gpr, uint64_t *cycle, unsigned int pc);

static int decode_exec(Decode *s, uint64_t *cycle) {
#ifdef CONFIG_ITRACE
  Decode *tmps = (Decode *)malloc(sizeof(Decode));
  tmps->pc = s->pc;
  tmps->snpc = s->snpc;
#endif

  int ebreak;
  step_one(&s->isa.inst.val, &ebreak, &s->dnpc, cpu.gpr, cycle, s->pc);
#ifdef CONFIG_ITRACE
  tmps->isa = s->isa;
  rb_add(s);
  free(tmps);
#endif

  if (ebreak) set_nemu_state(NEMU_END, s->pc, R(10));

  return 0;
}

int isa_exec_once(Decode *s, uint64_t *cycle) {
  s->isa.inst.val = inst_fetch(&s->snpc, 4);
  return decode_exec(s, cycle);
}
